#include "HttpConnection.h"
#include "../log.h"
#include "Logic.h"
#include "../Singleton.h"
#include "../utilities.h"

#include <boost/core/ignore_unused.hpp>

HttpConnection::HttpConnection(IOContext& io_context)
:_socket(io_context)
{

}

void HttpConnection::Start()
{
    auto self = shared_from_this();

    boost::beast::http::async_read(
        _socket, _buffer, _request,
        [self](boost::beast::error_code ec, std::size_t bytes_transferred) {
            try
            {
                if(ec)
                {
                    log_error("HttpConnection::Start async_read error: {}, from: {}"
                        , ec.message(), EndpointToString(self->_socket.remote_endpoint()));
                    return;
                }

                boost::ignore_unused(bytes_transferred);
                self->_HandleReq();
                self->_CheckDeadline();
            }
            catch (const std::exception& exp)
            {
                log_error("HttpConnection::Start exception: {}", exp.what());
            }
        });
}



void HttpConnection::_CheckDeadline()
{
    auto self = shared_from_this();
    
    _deadline.async_wait(
        [self](const boost::beast::error_code& ec) {
            if(!ec)
            {
                self->_socket.close();
            }
        });
}

void HttpConnection::_WriteResponse()
{
    auto self = shared_from_this();

    _response.content_length(_response.body().size());
    boost::beast::http::async_write(
        _socket, _response,
        [self](boost::beast::error_code ec, std::size_t bytes_transferred) {
            if(ec)
            {
                log_warning("HttpConnection::_WriteResponse error: {}, from: {}"
                    , ec.message(), EndpointToString(self->_socket.remote_endpoint()));
            }

            boost::ignore_unused(bytes_transferred);
            self->_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
            self->_deadline.cancel(); //取消定时器
        });
}

void HttpConnection::_HandleReq()
{
    _response.version(_request.version());
    _response.keep_alive(false);

    if(_request.method() == boost::beast::http::verb::get)
    {
        _PreParseGetParam(); //解析 GET 请求参数
        bool success = Singleton<Logic>::GetInstance()->HandleGet(_get_url, shared_from_this());
        if(!success)
        {
            _response.result(boost::beast::http::status::not_found);
            _response.set(boost::beast::http::field::content_type, "text/plain");
            boost::beast::ostream(_response.body())
                << "The resource '" << _get_url << "' was not found.";
            _WriteResponse();
            return;
        }

        _response.result(boost::beast::http::status::ok);
        _response.set(boost::beast::http::field::server, "MYChatServer");
        _WriteResponse();
        return;
    }
    else if(_request.method() == boost::beast::http::verb::post)
    {
        bool success = Singleton<Logic>::GetInstance()->HandlePost(std::string(_request.target().data(), _request.target().size()), shared_from_this());
        if(!success)
        {
            _response.result(boost::beast::http::status::not_found);
            _response.set(boost::beast::http::field::content_type, "text/plain");
            boost::beast::ostream(_response.body())
                << "The resource '" << _request.target() << "' was not found.";
            _WriteResponse();
            return;
        }
        _response.result(boost::beast::http::status::ok);
        _response.set(boost::beast::http::field::server, "MYChatServer");
        _WriteResponse();
        return;
    }
    else
    {
        _response.result(boost::beast::http::status::bad_request);
        _response.set(boost::beast::http::field::content_type, "text/plain");
        boost::beast::ostream(_response.body())
            << "Unknown HTTP-method";
        _WriteResponse();
        return;
    }
}



//将字符转为十六进制
char nibbleToHex(unsigned char nibble) 
{
    static const char* hexDigits = "0123456789ABCDEF";
    return hexDigits[nibble & 0x0F];
}
//将十六进制转为字符
unsigned char hexToNibble(char c) {
    if (c >= '0' && c <= '9') return static_cast<unsigned char>(c - '0');
    if (c >= 'A' && c <= 'F') return static_cast<unsigned char>(c - 'A' + 10);
    if (c >= 'a' && c <= 'f') return static_cast<unsigned char>(c - 'a' + 10);
    throw std::invalid_argument("Invalid hex digit");
}

std::string UrlEncode(const std::string& str)
{
    std::string out;
    out.reserve(str.size() * 3); // 最坏情况所有字符都需要转义

    for (unsigned char c : str) {
        if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            out.push_back(c);
        } else if (c == ' ') {
            out.push_back('+');
        } else {
            out.push_back('%');
            out.push_back(nibbleToHex(c >> 4));
            out.push_back(nibbleToHex(c & 0x0F));
        }
    }
    return out;
}

std::string UrlDecode(const std::string& str)
{
    std::string out;
    out.reserve(str.size());

    for (size_t i = 0; i < str.size(); ++i) {
        char c = str[i];
        if (c == '+') {
            out.push_back(' ');
        } else if (c == '%') {
            if (i + 2 >= str.size()) {
                throw std::invalid_argument("Incomplete percent-encoding");
            }
            unsigned char high = hexToNibble(str[++i]);
            unsigned char low  = hexToNibble(str[++i]);
            out.push_back(static_cast<char>((high << 4) | low));
        } else {
            out.push_back(c);
        }
    }
    return out;
}


void HttpConnection::_PreParseGetParam() {
    // 获取 URI
    std::string uri = std::string(_request.target().data(), _request.target().size());

    // 分离路径和查询字符串
    size_t query_pos = uri.find('?');
    if (query_pos == std::string::npos) {
        _get_url = uri;
        return;
    }
    _get_url.assign(uri.data(), query_pos); // 避免 substr 分配

    // 遍历查询参数
    const char* p = uri.data() + query_pos + 1;
    const char* end = uri.data() + uri.size();

    while (p < end) {
        // 找到 '=' 或 '&'
        const char* key_start = p;
        const char* eq = std::find(p, end, '=');
        const char* amp = std::find(p, end, '&');

        if (eq != end && eq < amp) {
            // 有 key=value
            std::string key   = UrlDecode(std::string(key_start, eq));
            std::string value = UrlDecode(std::string(eq + 1, amp));
            _get_params.emplace(std::move(key), std::move(value));
        }
        // 如果没有 '='，则跳过（只有 key，没有 value）
        else if (amp > key_start) {
            std::string key = UrlDecode(std::string(key_start, amp));
            _get_params.emplace(std::move(key), "");
        }

        // 移动到下一个参数
        p = (amp == end) ? end : (amp + 1);
    }
}